#include "BasicBlock.hpp"
#include "Constant.hpp"
#include "Function.hpp"
#include "IRBuilder.hpp"
#include "Module.hpp"
#include "Type.hpp"

#include <iostream>
#include <memory>

// 定义一个宏，用于简化常量整数的创建
#define CONST_INT(num) ConstantInt::get(num, module)

// 生成 IR 的主函数
void generateIR(Module* module) {
    // 创建 IR 构建器和基本类型
    auto builder = new IRBuilder(nullptr, module);
    Type* Int32Type = module->get_int32_type();

    // 创建 main 函数
    auto mainFun = Function::create(FunctionType::get(Int32Type, {}), "main", module);
    auto entryBB = BasicBlock::create(module, "entry", mainFun);
    builder->set_insert_point(entryBB);

    // 分配变量 b 并初始化为 1
    auto bAlloca = builder->create_alloca(Int32Type);
    builder->create_store(CONST_INT(1), bAlloca); // b = 1

    // 分配数组 a（大小为 20）
    auto arrayType = ArrayType::get(Int32Type, 20);
    auto aAlloca = builder->create_alloca(arrayType);

    // 初始化 a[0] = 28
    auto a0GEP = builder->create_gep(aAlloca, {CONST_INT(0), CONST_INT(0)});
    builder->create_store(CONST_INT(28), a0GEP);

    // 计算 a[1] = a[0] / 2
    auto a0Load = builder->create_load(a0GEP);
    auto a1 = builder->create_isdiv(a0Load, CONST_INT(2));
    auto a1GEP = builder->create_gep(aAlloca, {CONST_INT(0), CONST_INT(1)});
    builder->create_store(a1, a1GEP);

    // 计算 a[2] = a[1] * 10
    auto a1Load = builder->create_load(a1GEP);
    auto a2 = builder->create_imul(a1Load, CONST_INT(10));
    auto a2GEP = builder->create_gep(aAlloca, {CONST_INT(0), CONST_INT(2)});
    builder->create_store(a2, a2GEP);

    // 计算 a[3] = a[2] - b
    auto bLoad = builder->create_load(bAlloca);
    auto a3 = builder->create_isub(builder->create_load(a2GEP), bLoad);
    auto a3GEP = builder->create_gep(aAlloca, {CONST_INT(0), CONST_INT(3)});
    builder->create_store(a3, a3GEP);

    // 返回 a[3]
    auto a3Load = builder->create_load(a3GEP);
    builder->create_ret(a3Load);

    // 清理资源
    delete builder;
}

int main() {
    // 创建模块并生成 IR
    auto module = new Module();
    generateIR(module);

    // 输出生成的 IR 指令
    std::cout << module->print();

    // 清理资源
    delete module;
    return 0;
}
